package ca.mcgill.mni.bic;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Arrays;

import org.apache.log4j.Logger;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.ModifyEvent;
import org.eclipse.swt.events.ModifyListener;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.layout.RowLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Group;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Menu;
import org.eclipse.swt.widgets.MenuItem;
import org.eclipse.swt.widgets.MessageBox;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Text;

/**
 * @author jharlap
 *
 */
public class SeriesInfoWidget extends Composite {
	
	static Logger logger = Logger.getLogger(SeriesInfoWidget.class);

//	private Text seriesCommentField;
	private Text seriesDescriptionField;
	private Label seriesNumberField, seriesNumSlicesField;
	
	private Color red;
	private Shell shell;
	private Series series;
	private Button saveButton;
	
	public SeriesInfoWidget(Composite parent, int style) {
		super(parent, style);
		shell = parent.getShell();
		
		red = shell.getDisplay().getSystemColor(SWT.COLOR_RED);
		
		final Group group = new Group(this, SWT.BORDER);
		group.setText("Series info");
		
		Config config = Config.singleton();
		
		Label seriesNumberLabel = new Label(group, SWT.NONE);
		seriesNumberLabel.setText("Series Number:");

		seriesNumberField = new Label(group, SWT.NONE);
		seriesNumberField.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
		
		Label seriesDescriptionLabel = new Label(group, SWT.NONE);
		seriesDescriptionLabel.setText("Series Description:");
		
		Menu seriesDescriptionMenu = new Menu(group.getShell(), SWT.POP_UP);
		for (String categoryName : config.seriesDescriptions.keySet()) {
			MenuItem categoryItem = new MenuItem(seriesDescriptionMenu, SWT.CASCADE);
			categoryItem.setText(categoryName);
			
			Menu submenu = new Menu(group.getShell(), SWT.DROP_DOWN);
			for(String descriptionName : config.seriesDescriptions.get(categoryName)) {
				MenuItem descItem = new MenuItem(submenu, SWT.CASCADE);
				descItem.setText(descriptionName);
				descItem.addSelectionListener(new SelectionListener() {
				      public void widgetSelected(SelectionEvent e) {
				            MenuItem item = (MenuItem) e.widget;
				            seriesDescriptionField.setText(item.getText());
				      }
				      public void widgetDefaultSelected(SelectionEvent e) {
				      }
				});

			}

			categoryItem.setMenu(submenu);
		}

		
		seriesDescriptionField = new Text(group, SWT.NONE);
		GridData gridData = new GridData(GridData.FILL_HORIZONTAL);
		gridData.minimumWidth = 300;
		seriesDescriptionField.setLayoutData(gridData);
		seriesDescriptionField.setMenu(seriesDescriptionMenu);
		
		seriesDescriptionField.addModifyListener(new ModifyListener() {

			public void modifyText(ModifyEvent event) {
				if(Series.isValidDescription(seriesDescriptionField.getText())) {
					seriesDescriptionField.setForeground(null);
				} else {
					seriesDescriptionField.setForeground(red);
				}
			}
		});
		
//		Label seriesCommentLabel = new Label(group, SWT.NONE);
//		seriesCommentLabel.setText("Comment:");
//		
//		seriesCommentField = new Text(group, SWT.MULTI);
//		GridData gridData = new GridData(300, 100);
//		seriesCommentField.setLayoutData(gridData);

		Label seriesNumSlicesLabel = new Label(group, SWT.NONE);
		seriesNumSlicesLabel.setText("Num Slices:");

		seriesNumSlicesField = new Label(group, SWT.NONE);
		seriesNumSlicesField.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
		
		// the buttons area
		Group buttons = new Group(this, SWT.BORDER);
		buttons.setText("Series operations");
		
		// the save button
		saveButton = new Button(buttons, SWT.PUSH);
		saveButton.setText("Save Changes");
		
		saveButton.addSelectionListener(new SelectionAdapter() {
			public void widgetSelected(SelectionEvent e) {
				updateHeaders();
			}
		});
		
		ModifyListener enableSaveButton = new ModifyListener() {
			public void modifyText(ModifyEvent event) {
				saveButton.setEnabled(canSave());
			}
		};
		
		seriesDescriptionField.addModifyListener(enableSaveButton);

		// the view button
		Button viewButton = new Button(buttons, SWT.PUSH);
		viewButton.setText("View Series");
		viewButton.addSelectionListener(new SelectionAdapter() {
			public void widgetSelected(SelectionEvent e) {
				displaySeries();
			}
		});

		buttons.setLayout(new RowLayout(SWT.HORIZONTAL));
		setLayout(new RowLayout(SWT.VERTICAL));

		GridLayout gridLayout = new GridLayout();
	    gridLayout.numColumns = 2;
	    group.setLayout(gridLayout);
	    
	}
	
	public void setSeries(Series series) {
		this.series = series;
		
		if(series.seriesDescription != null)
			seriesDescriptionField.setText(series.seriesDescription);
		
		if(series.seriesNumber != null)
			seriesNumberField.setText(Integer.toString(series.seriesNumber));
		
		if(series.numSlices != null)
			seriesNumSlicesField.setText(Integer.toString(series.numSlices));
	}
	
	private boolean canSave() {
		if(series == null) return false;
		
		if(!seriesDescriptionField.getText().equalsIgnoreCase(series.seriesDescription)) {
			return true;
		}
		
		return false;
	}
	
	private void displaySeries() {
		
		MessageBox warn = new MessageBox(shell);
		warn.setMessage("The DICOM viewer has not yet been adapted to MacOS.\nPlease contact Samir to complain.");
		return;
/*		
		Runtime runtime = Runtime.getRuntime();
		String[] command = {"displaySeries.pl", series.parentStudy.getPath(), Integer.toString(series.seriesNumber)};
		try {
			runtime.exec(command);
		} catch (IOException e) {
			MessageBox warn = new MessageBox(shell);
			warn.setText("Error");
			warn.setMessage("Could not open viewer.  Please contact support.\n" + e.getMessage());
			warn.open();
		}
*/
	}
	
	private void updateHeaders() {
		Runtime runtime = Runtime.getRuntime();
		String[] command = {"updateHeaders.pl", "-verbose", "-database", "-profile", "ibis", "-series", Integer.toString(series.seriesNumber),
				"-set", "SeriesDescription", seriesDescriptionField.getText(),
				series.parentStudy.getPath()};
		
		logger.info("Updating headers for tarchiveID " + series.parentStudy.tarchiveID + " series num " + series.seriesNumber + " (" + series.seriesDescription + ")");
		logger.debug("Running: " + Arrays.toString(command));
		ProgressDialog progress = new ProgressDialog(shell, SWT.INDETERMINATE);

		try {
			
			boolean done = false;
			int exitValue = 0;
			progress.open("Updating headers, please wait. (This can take\na while you might want to get some coffee...)");
			Process proc = runtime.exec(command);
			BufferedReader procError = new BufferedReader(new InputStreamReader(proc.getErrorStream()));
			BufferedReader procOutput = new BufferedReader(new InputStreamReader(proc.getInputStream()));

			while (!done) {
				String outLine, errLine;
				if(procOutput.ready()) {
					outLine = procOutput.readLine();
					System.out.println(outLine);
					logger.debug(outLine);
				}
				
				if(procError.ready()) {
					errLine = procError.readLine();
					System.out.println(errLine);
					logger.debug(errLine);
				}
				try {
					exitValue = proc.exitValue();
					done = true;
				} catch (IllegalThreadStateException e) {
					progress.update();
				}
			}
			
			if(exitValue != 0) {
				logger.info("Update failure - exit code " + exitValue);
				MessageBox warn = new MessageBox(shell);
				warn.setText("Error");
				warn.setMessage("Header update had an error.  Please contact support.");
				warn.open();
			}
			
		} catch (IOException e) {
			logger.info("Update failure - message: " + e.getMessage());
			MessageBox warn = new MessageBox(shell);
			warn.setText("Error");
			warn.setMessage("Could not update headers.  Please contact support.\n" + e.getMessage());
			warn.open();
		}
		
		progress.close();
		logger.debug("Update complete");
	}

}  // end StudyInfoWidget
